package com.gitee.openviducn.inspector.auth;

import com.gitee.openviducn.inspector.constant.SymbolConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @Author: https://gitee.com/wesleyOne
 * @Date: 03.02 2020
 * 参考[https://github.com/alibaba/Sentinel/]控制台项目
 */
@Slf4j
@Component
public class LoginAuthenticationFilter implements Filter {

    private static final String URL_SUFFIX_DOT = ".";

    /**
     * 不需要校验的路由
     */
    @Value("#{'${auth.filter.exclude-urls}'.split(',')}")
    private List<String> authFilterExcludeUrls;

    /**
     * 不需要校验的路由后缀
     */
    @Value("#{'${auth.filter.exclude-url-suffixes}'.split(',')}")
    private List<String> authFilterExcludeUrlSuffixes;

    @Resource
    private AuthService<HttpServletRequest> authService;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;

        String servletPath = httpRequest.getServletPath();

        // 排除不需要校验的路由
        if (authFilterExcludeUrls.contains(servletPath)) {
            chain.doFilter(request, response);
            return;
        }

        // 排除不需要校验的路由后缀
        for (String authFilterExcludeUrlSuffix : authFilterExcludeUrlSuffixes) {
            if (StringUtils.isBlank(authFilterExcludeUrlSuffix)) {
                continue;
            }

            // Add . for url suffix so that we needn't add . in property file
            if (!authFilterExcludeUrlSuffix.startsWith(SymbolConstant.URL_SUFFIX_DOT)) {
                authFilterExcludeUrlSuffix = SymbolConstant.URL_SUFFIX_DOT + authFilterExcludeUrlSuffix;
            }

            if (servletPath.endsWith(authFilterExcludeUrlSuffix)) {
                chain.doFilter(request, response);
                return;
            }
        }

        AuthService.AuthUser authUser = authService.getAuthUser(httpRequest);
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        if (authUser == null) {
            // If auth fail, set response status code to 401
            httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        } else {
            chain.doFilter(request, response);
        }
    }
}
